<?php

namespace app\controller;

use app\BaseController;
use app\dao\CategoryDao;
use app\model\Category;
use app\model\File;
use app\model\Orders;
use app\model\Project;
use app\model\User;
use think\App;
use think\facade\Cache;
use think\facade\View;
use think\facade\Db as db;
use think\file\UploadedFile;
use think\Http;
use think\Image;
use think\Model;
use think\Request;
use app\utils\simple_html_dom;


class Index extends BaseController
{
    var $userModel;
    var $categoryModel;
    var $bannerModel;
    var $menuModel;
    var $courseModel;

    public function __construct(App $app)
    {
        parent::__construct($app);
        $this->userModel = new User();
        $this->categoryModel = new Category();
        $this->bannerModel = new \app\model\CmsBanner();
        $this->menuModel = new \app\model\Menu();
        $this->courseModel = new \app\model\Course();
    }


    //首页
    public function index()
    {
        $bannerList = $this->bannerModel->where('enable',1)->select();
        View::assign('bannelList', $bannerList);


        $courseList = $this->courseModel->where('state',3)->select();
        View::assign('courseList', $courseList);


        return view("/index");
    }

    public function code0()
    {
        return $this->code('all');
    }
    public function code($code)
    {
        session('last_uri', $_SERVER['REQUEST_URI']);
        $request = request();
        $page = $request->get('page',1);
        $sort = $request->get('sort',1);
        $rows = 10;
        $key = 'html_code_'.$code.'_'.$page.'_'.$sort;
        $cache = Cache::store('redis');
        $content = $cache->get($key);
        if ($content != null) {
            echo '<!--from cache-->';
            //return $content;
        }
        echo '<!--no cache-->';

        $pro = new Project();
        $q = $pro->where('status', '=', 1);
        if ($code != 'all') {
            //$cc = Category::where('code',$code)->find();
            $catedao = new CategoryDao();
            $cc = $catedao->getByCode($code);
            if ($cc!=null) {
                $q->where('category_id', $cc['id']);
            }
        }else{
            $cc = ['id'=>0,'name'=>'全部','code'=>'all'];
        }
        if ($sort == 1) { //默认排序（最新）
            $q->order('create_time','desc');
        } elseif ($sort == 2) { //最热（最多下载量）
            $q->order('down_','desc');
        } elseif ($sort == 3) { //最贵
            $q->order('price','desc');
        }

        $list = $q->paginate([
                'list_rows'=>$rows,'page'=>$page
            ]);

        $total = $list->total();
        $pages =  ceil($total/$rows);
        $rets = [
            'total'=>$list->total(),                    //总记录数
            'pages'=>$pages,                            //总页数
            'curr'=>$page,                              //当前第几页
            'rows'=>$rows,                              //每页记录数
            'prev'=>$page<2?1:$page-1,                  //上一页
            'next'=>$page>$pages-1?$pages:$page+1,      //下一页
            'list'=>$list,                               //数据列表
            'sort'=>$sort                               //排序参数
        ];

        //生成缩略图
        $this->project_thumb($list);

        View::assign('pn', 'code');
        $content = view("/code", ['rets'=>$rets,'cc'=>$cc])->getContent();
        $cache->set($key, $content, 3600 );
        return $content;
    }

    public function share($id)
    {
        session('last_uri', $_SERVER['REQUEST_URI']);
        $projectModel = new Project();
        $q = $projectModel->where('id', '=', $id);
        $project = $q->find();

        //每个session第一次访问时增加访问次数
        $vk_ = 'view_'.$id;
        if (session($vk_) == null) {
            $project->set('view_',$project->view_+1);
            $project->save();
            session($vk_, 1);
        }

        //session('login_user_id', null);

        View::assign('project', $project);
        View::assign('pn', 'share');
        $content = view("/share")->getContent();
        return $content;;
    }

    // 检测项目是否可以下载
    public function check2($projectId)
    {
        // 1.检测是否登录
        $user_ = loginUser();
        if ($user_ == null) {
            return ['code'=>1,'msg'=>'未登录'];
        }
        // 2.检测登录用户是否存在
        $userModel = new User();
        $user = $userModel->where('id', $user_->id)->find();
        if ($user == null) {
            return ['code'=>2,'msg'=>'登录信息无效'];
        }

        // 3.检测项目是否存在
        $projectModel = new Project();
        $project = $projectModel->where('id','=',$projectId)->find();
        if ($project == null) {
            return ['code'=>3,'user'=>$user];
        }
        // 4.检测文件信息是否存在
        if ($project->file == null) {
            return ['code'=>4,'user'=>$user,'project'=>$project];
        }
        // 检测是否自己
        if ($user->id == $project->user->id) {
            return ['code'=>6,'user'=>$user,'project'=>$project]; //拥有此资源
        }
        // 检测是否购买过
        $order = Db::table('orders')
            ->where('project_id', '=',$project->id)
            ->where('user_id', '=',$user->id)->find();
        if ($order != null) {
            return ['code'=>6,'user'=>$user,'project'=>$project]; //拥有此资源
        }
        // 检测余额是否充足
        if ($user->coin < $project->price) {
            return ['code'=>5,'user'=>$user,'project'=>$project];
        }
        return ['code'=>0,'user'=>$user,'project'=>$project];
    }

    public function api_check_download($project_id)
    {
        $request_ = request();

        $num = $this->check2($project_id)['code'];

        switch ($num) {
            case 0:return json_encode(['code'=>0, 'msg' => '可以购买'],JSON_UNESCAPED_UNICODE);
            case 1:return json_encode(['code'=>1, 'msg' => '未登录'],JSON_UNESCAPED_UNICODE);
            case 2:return json_encode(['code'=>2, 'msg' => '登录信息无效'],JSON_UNESCAPED_UNICODE);
            case 3:return json_encode(['code'=>3, 'msg' => '资源不存在'],JSON_UNESCAPED_UNICODE);
            case 4:return json_encode(['code'=>4, 'msg' => '文件缺失'],JSON_UNESCAPED_UNICODE);
            case 5:return json_encode(['code'=>5, 'msg' => '积分不足'],JSON_UNESCAPED_UNICODE);
            case 6:return json_encode(['code'=>6, 'msg' => '已拥有此资源'],JSON_UNESCAPED_UNICODE);
        }
        return json_encode(['code'=>500, 'msg' => '兄弟你真你牛逼，500都被你搞出来了！'],JSON_UNESCAPED_UNICODE);
    }

    //下载文件
    public function download($id)
    {
        $uri = $_SERVER["REQUEST_URI"];
        $host = @$_SERVER["HTTP_HOST"];
        if (strpos($host, '127.0.0.1')!==false or strpos($host, 'localhost')!==false ) {
            echo '本地环境无法下载';
            return;
        }
        $ck = $this->check2($id);
        $code = $ck['code'];
        if ($code != 0 and $code!=6) {
            return json_encode(['code'=>500, 'msg' => '您无法下载这个资源哦老铁！'],JSON_UNESCAPED_UNICODE);
        }

        $user = $ck['user'];
        $project = $ck['project'];
        $file = $project->file;

        //如果购买过此资源
        if ($code == 6) {
            goto ksxz; //开始下载
        }

        if ($user->vip <= 0) {
            //print_r('普通用户|正常购买');
            if ($user->coin < $project->price) {
                return json_encode(['code'=>500, 'msg' => '老铁，你积分不足了哟！'],JSON_UNESCAPED_UNICODE);
            }else{
                //正常购买
                Db::startTrans();
                try{
                    //购买者扣除余额
                    Db::table('user')->where('id',$user->id)->dec('coin', $project->price)->update();
                    //发布者增加余额
                    Db::table('user')->where('id',$project->user->id)->inc('coin', $project->price)->update();
                    //保存订单
                    Db::table('orders')->insert([
                        'project_id'=>$project->id,
                        'user_id'=>$user->id,
                        'price'=>$project->price,
                        'vip'=>$user->vip,
                    ]);
                    //硬币记录:购买者
                    Db::table('coin_record')->insert([
                        'user_id'=>$user->id,
                        'coin'=> -$project->price,
                        'reason'=>'下载资源',
                        'project_id'=>$project->id,
                    ]);
                    //硬币记录:发布者
                    Db::table('coin_record')->insert([
                        'user_id'=>$project->user->id,
                        'coin'=> $project->price,
                        'reason'=>'资源被下载',
                        'project_id'=>$project->id,
                    ]);
                    Db::commit();
                } catch (\Exception $e) {
                    Db::rollback();
                    return json_encode(['code'=>500, 'msg' => '兄弟你真牛逼，500都被你搞出来了！'],JSON_UNESCAPED_UNICODE);
                }
            }
        }else{
            //echo 'VIP免费下载|';
        }

        ksxz: //开始下载
        //echo '开始下载|';

        //更新下载数，每次session记录1次
        $xzbjKey = 'downloaded_project_' . $project->id;
        $xzbj = session($xzbjKey);
        if ($xzbj == null) {
            //echo '下载次数+1|';
            Db::table('project')->where('id', $project->id)->inc('down_')->update();
            session($xzbjKey,1);
        }

        //下载文件
        $showName = '【酷代码】'.$file->original_name;
        header("Content-type: application/octet-stream");
        header('Content-Disposition: attachment; filename="'. $showName .'"');
        header("X-Accel-Redirect:/file/code/".$file->md5);

    }


    //发表项目的页面
    public function share_create_html()
    {
        $user = loginUser();
        if ($user == null) {
            return redirect('/');
        }
        $langs = Db::table('category')->select();
        View::assign('langs', $langs);

        session('publish_ticket', uuid());

        return view('/share_create');
    }


    public function upload(){

        $user = loginUser();
        if ($user == null) {
            return json_encode([
                'errno'=>1,
                'msg'=>'未登录，无法上传图片'
            ],JSON_UNESCAPED_UNICODE);
        }

        // 获取表单上传文件
        $files = request()->file();

        try {
            // 1M => 1048576
            //validate(['image'=>'filesize:2097152|fileExt:jpg|image:200,200,jpg'])->check($files);
            validate(['image'=>'fileSize:1048576|fileExt:jpg,png,gif,jpeg,bmp,webp,jfif'],[],true,true)->check($files);
        } catch (\think\exception\ValidateException $e) {
            return json_encode([
                'errno'=>2,
                'msg'=>'图片超过1M限制或后缀名不规范'
            ],JSON_UNESCAPED_UNICODE);
        }

        $data = [];

        $conn = ftp_connect("49.232.143.254");
        try {
            //登录到FTP服务器
            ftp_login($conn, "img", "nSyEBfmcX3H6ZzrZ");
            ftp_pasv($conn, true);

            foreach($files as $file){
                //file是接收到的临时文件
                $size_ = filesize($file); //字节数
                $md5_ = md5_file($file);

                $path = '/' . $md5_.'.jpg';
                $url = 'http://res.itsub.cn/img'.$path;

                $row = Db::table('img')->where('md5', $md5_)->find();
                if ($row == null) {

                    $info = ftp_put($conn, $path, $file,FTP_BINARY);
                    if ($info) {
                        Db::table('img')->insert([
                            'md5'=>$md5_,
                            'size'=>$size_,
                            'user_id'=>$user->id,
                        ]);
                    }else{
                        //ftp上传失败
                        return json_encode([
                            'errno'=>3,
                            'msg'=>'上传失败，服务端存储异常'
                        ],JSON_UNESCAPED_UNICODE);
                    }

                }
                array_push($data,['url'=>$url,'alt'=>'','href'=>'']);

            }

        } catch (\Exception $e) {
            return json_encode([
                'errno'=>4,
                'msg'=>'未知异常'
            ],JSON_UNESCAPED_UNICODE);
        } finally {
            ftp_quit($conn);
        }


        return json_encode([
            'errno'=>0,
            'data'=>$data
        ],JSON_UNESCAPED_UNICODE);
    }

    public function clear(Request $request)
    {
        Cache::clear();
        return json_encode([
            'code'=>0,'msg'=>'缓存清理成功'
        ]);
    }

    public function setloginuser($id)
    {
        $userModel = new \app\model\User();
        $user = $userModel->where('id', '=', $id)->find();
        session('login_user_id', $id);
        session('login_user', $user);
        return json_encode([
            'code'=>0,'msg'=>'登录用户设置为：'.$id,
            'user'=>$user
        ],JSON_UNESCAPED_UNICODE);
    }


    public function api_project_save()
    {
        $user = loginUser();
        if ($user == null) {
            return json_encode(['code'=>1,'msg'=>'未登录'],JSON_UNESCAPED_UNICODE);
        }

        $file_id = 0;
        $file = null;

        $request_ = request();

        $ticket = session('publish_ticket');
        if ($ticket == null or $request_->param('ticket') != $ticket) {
            //4号以内的id都不需要验证凭据
            if ($user->id > 4) {
                return json_encode(['code'=>5,'msg'=>'凭据无效，请勿重复提交'],JSON_UNESCAPED_UNICODE);
            }
        }


        $categoryId = $request_->param('category');
        $title = trim($request_->param('title'));
        $content = trim($request_->param('content'));
        $tags = $request_->param('tag/a');

        //表单验证，防止空值
        if (empty($categoryId) or empty($title) or empty($content)) {
            return json_encode(['code'=>2,'msg'=>'参数接收异常'],JSON_UNESCAPED_UNICODE);
        }

        //上传文件，超过php限制时file为空，且其他属性也接收不到
        if ($categoryId == null and $file == null and $title==null) {
            //基本可以断定，超出了php限制
            return json_encode(['code'=>2,'msg'=>'参数接收异常'],JSON_UNESCAPED_UNICODE);
        }

        //标题不能重复
        if ($this->projectModel->where('name', $title)->find()!=null) {
            return json(['code' => 3, 'msg' => '存在相同标题，请修改后重试']);
        }

        if($_FILES['file']['name']){ //如果上传了文件
            $file = $request_->file('file');
        }

        if ($file != null) {
            $md5_ = $file->md5();
            $size = $file->getSize();

            if ($size > 10485760) { //如果大于10M
                return json_encode([
                    'code'=>4,
                    'msg'=>'文件超过10M限制'
                ],JSON_UNESCAPED_UNICODE);
            }

            $info = Db::table('file')->where('md5')->find();
            if ($info == null) {
                cc_ftp_file_upload('/code/'.$md5_,$file);
                $file_id = Db::table('file')->insert([
                    'original_name'=>$file->getOriginalName(),
                    'original_extension'=>$file->getOriginalExtension(),
                    'md5'=>$md5_,
                    'sha1'=>$file->sha1(),
                    'size'=>$size,
                    'state'=>0,
                ],true);
            }else{
                $file_id = $info['id'];
            }

        }

        Db::startTrans();
        try {
            //保存项目
            $pid = Db::table('project')->insert([
                'category_id'=>$categoryId,
                'name'=>$title,
                'user_id'=>$user->id,
                'status'=>1,
                'content'=>$content,
                'file_id'=>$file_id,
                'price'=>50,
            ],true);
            //更改文件状态为'已确认'
            if ($file_id != 0) {
                Db::table('file')->where('id',$file_id)->update(['state' => 1]);
            }

            //扣除用户积分
            Db::table('user')->where('id', $user->id)->dec('coin', 2)->update();

            //保存标签
            if (is_array($tags)) {
                foreach ($tags as $tagName) {
                    $tagName = strtolower($tagName);
                    $tid = 0;
                    //如果没有标签则创建
                    $tag = Db::table('tags')->where('name', $tagName)->find();
                    if ($tag == null) {
                        $tid = Db::table('tags')->insert([
                            'name'=>$tagName,
                        ],true);
                    }else{
                        $tid = $tag['id'];
                    }
                    //添加关联
                    $pt = Db::table('project_tags')->where('project_id', $pid)->where('tags_id', $tid)->find();
                    if ($pt == null) {
                        Db::table('project_tags')->insert([
                            'project_id'=>$pid,
                            'tags_id'=>$tid,
                        ]);
                    }

                }
            }
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
        }


        //删除凭据
        session('publish_ticket', null);

        return json_encode(['code'=>0, 'msg' => '项目提交成功，请等待管理员审核！'],JSON_UNESCAPED_UNICODE);
    }


    public function api_project_update()
    {
        $user = loginUser();
        if ($user == null) {
            return json_encode(['code'=>1,'msg'=>'未登录'],JSON_UNESCAPED_UNICODE);
        }

        $file_id = 0;
        $file = null;

        $request_ = request();

        if($_FILES['file']['name']){ //如果上传了文件
            $file = $request_->file('file');
        }

        $projectId = $request_->param('project_id');
        $categoryId = $request_->param('category');
        $title = trim($request_->param('title'));
        $content = trim($request_->param('content'));
        $tags = $request_->param('tag/a');
        $status = $request_->param('status');

        //表单验证，防止空值
        if (empty($categoryId) or empty($title) or empty($content)) {
            return json_encode(['code'=>2,'msg'=>'参数接收异常'],JSON_UNESCAPED_UNICODE);
        }

        //上传文件，超过php限制时file为空，且其他属性也接收不到
        if ($categoryId == null and $file == null and $title==null) {
            //基本可以断定，超出了php限制
            return json_encode(['code'=>2,'msg'=>'参数接收异常'],JSON_UNESCAPED_UNICODE);
        }

        Db::startTrans();
        try {
            if ($file != null) {
                $md5_ = $file->md5();
                $size = $file->getSize();

                if ($size > 10485760) { //如果大于10M
                    return json_encode([
                        'code'=>3,
                        'msg'=>'文件超过10M限制'
                    ],JSON_UNESCAPED_UNICODE);
                }

                $info = Db::table('file')->where('md5',$md5_)->find();
                if ($info == null) {
                    cc_ftp_file_upload('/code/'.$md5_,$file);
                    $file_id = Db::table('file')->insert([
                        'original_name'=>$file->getOriginalName(),
                        'original_extension'=>$file->getOriginalExtension(),
                        'md5'=>$md5_,
                        'sha1'=>$file->sha1(),
                        'size'=>$size,
                        'state'=>0,
                    ],true);
                }else{
                    $file_id = $info['id'];
                }

            }

            //保存项目
            Db::table('project')->where('id',$projectId)->update([
                'category_id'=>$categoryId,
                'name'=>$title,
                'status'=>$status,
                'content'=>$content,
            ]);
            //更改文件状态为'已确认'
            if ($file_id != 0) {
                Db::table('project')->where('id',$projectId)->update(['file_id'=>$file_id]);
                Db::table('file')->where('id',$file_id)->update(['state' => 1]);
            }

            //删除现有标签
            Db::table('project_tags')->where('project_id', $projectId)->delete();
            //保存新标签
            if (is_array($tags)) {
                foreach ($tags as $tagName) {
                    //如果没有标签则创建标签
                    $tag = $this->TagByName($tagName);
                    Db::table('project_tags')->insert([
                        'project_id'=>$projectId,
                        'tags_id'=>$tag['id'],
                    ]);
                }
            }
            Db::commit();
        }catch (\Exception $e){
            echo $e;
            Db::rollback();
            return json_encode(['code'=>1, 'msg' => '修改异常！'],JSON_UNESCAPED_UNICODE);
        }

        return json_encode(['code'=>0, 'msg' => '修改成功！'],JSON_UNESCAPED_UNICODE);
    }

    //获取tag信息，没有则创建并返回
    private function TagByName($name)
    {
        $tag = Db::table('tags')->where('name', $name)->find();
        if ($tag == null) {
            $tid = Db::table('tags')->insert([
                'name'=>$name,
            ],true);
            $tag = Db::table('tags')->where('name', $name)->find();
        }
        return $tag;
    }


    public function tools_html(){
        return \view('/tools');
    }
    public function qqq_html(){
        return \view('/qqq');
    }
    public function buy_html(){
        return \view('/buy');
    }


    public function logout(){
        session('login_user', null);
        return redirect('/');
    }

    public function register_html()
    {
        return \view('/register');
    }

    public function register_do()
    {
        $email = \request()->param('email');
        SendMail($email,'【酷代码】注册成功','【酷代码】恭喜您注册成功，您的幸运数字：'.random_int(1,99999));
        echo '邮件发送完成';
    }

    public function project_edit_html($id)
    {
        $user = loginUser();
        if ($user == null or $user->id != 4) {
            return redirect('/');
        }
        $project = $this->projectModel->where('id', $id)->find();
        View::assign('project', $project);
        return \view('/project_edit');
    }

    public function search()
    {
        session('last_uri', $_SERVER['REQUEST_URI']);
        $request = request();
        $page = $request->get('page',1);
        $key = $request->get('key','');
        $keyArray = explode(" ", $key);
        $rows = 10;

        $pro = new Project();
        $q = $pro->where('status', '=', 1);
        foreach ($keyArray as $word) {
            $q->whereLike('name', '%'.$word.'%', 'and');
        }
        $q->order('down_','desc');

        $list = $q->paginate([
            'list_rows'=>$rows,'page'=>$page
        ]);

        $total = $list->total();
        $pages =  ceil($total/$rows);
        $rets = [
            'total'=>$list->total(),                    //总记录数
            'pages'=>$pages,                            //总页数
            'curr'=>$page,                              //当前第几页
            'rows'=>$rows,                              //每页记录数
            'prev'=>$page<2?1:$page-1,                  //上一页
            'next'=>$page>$pages-1?$pages:$page+1,      //下一页
            'list'=>$list,                               //数据列表
            'key'=>$key,
        ];

        $this->project_thumb($list);

        $content = view("/search", ['rets'=>$rets])->getContent();
        return $content;
    }

    /** 项目生成缩略图 */
    function project_thumb($list)
    {
        //生成缩略图
        $conn = cc_ftp_conn();
        try {
            foreach ($list as $project){
                $html = new simple_html_dom();
                $html->load($project->content);
                $arr = [];
                foreach($html->find('img') as $img){
                    $src = $img->src;
                    $name = md5($src) . '.jpg';
                    $path = '/m/' . $name;
                    array_push($arr, 'http://res.itsub.cn/img'.$path);
                    //判断ftp文件是否存在
                    if (ftp_size($conn,$path) == -1) {
                        $tmp = root_path('public') . 'tmp/'.$name.'.tmp'; //原图
                        $tmp2 = root_path('public') . 'tmp/'.$name.'.tmp2';//缩略图
                        try {
                            ob_start();//打开输出
                            readfile($src);//输出图片文件
                            $t = ob_get_contents();//得到浏览器输出
                            ob_end_clean();//清除输出并关闭
                            //$size = strlen($img);//得到图片大小
                            $fp2 = @fopen($tmp, "a");
                            fwrite($fp2, $t);//向当前目录写入图片文件，并重新命名
                            fclose($fp2);
                            $image = Image::open($tmp);
                            $image->thumb(120,120)->save($tmp2,'jpg',95);
                            ftp_put($conn, $path, $tmp2, FTP_BINARY);
                        } finally {
                            unlink($tmp);
                            unlink($tmp2);
                        }
                    }

                }
                $project->imgs = $arr;
            }
        } finally {
            ftp_close($conn);
        }
    }


    public function project_info($id)
    {
        $project = $this->projectModel->where('id', $id)->find();
        return json(['code'=>0,'data'=>$project]);
    }
}
